home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / os2 / gnuwget.zip / wget-1.4.3 / src / connect.c < prev    next >
C/C++ Source or Header  |  1997-02-08  |  7KB  |  275 lines

  1. /* Establishing and handling network connections.
  2.    Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
  3.    
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2 of the License, or
  7.    (at your option) any later version.
  8.    
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.    
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. #ifdef HAVE_CONFIG_H
  19. #  include <config.h>
  20. #endif /* HAVE_CONFIG_H */
  21. #include "systhings.h"
  22.  
  23. #include <stdio.h>
  24. #include <sys/types.h>
  25. #ifdef HAVE_UNISTD_H
  26. #  include <unistd.h>
  27. #endif
  28.  
  29. #ifdef WINDOWS
  30. #  include <winsock.h>
  31. #  include "windecl.h"
  32. #else
  33. #  include <sys/socket.h>
  34. #  include <netdb.h>
  35. #  include <netinet/in.h>
  36. #  include <arpa/inet.h>
  37. #endif /* WINDOWS */
  38.  
  39. #include <errno.h>
  40. #ifdef HAVE_STRING_H
  41. #  include <string.h>
  42. #else
  43. #  include <strings.h>
  44. #endif /* HAVE_STRING_H */
  45. #ifdef HAVE_SYS_SELECT_H
  46. #  include <sys/select.h>
  47. #endif /* HAVE_SYS_SELECT_H */
  48.  
  49. #include "wget.h"
  50. #include "options.h"
  51. #include "utils.h"
  52. #include "connect.h"
  53. #include "host.h"
  54.  
  55. #ifndef errno
  56. extern int errno;
  57. #endif
  58.  
  59. extern struct options opt;
  60.  
  61. /* Global variables share by bindport and acceptport: */
  62. int msock = -1, addrlen;
  63. struct sockaddr *addr;
  64. struct sockaddr_in srv;
  65.  
  66.  
  67. uerr_t
  68. make_connection(int *sock, char *hostname, unsigned short port)
  69. {
  70.    struct sockaddr_in sock_name;
  71.    /* struct hostent *hptr; */
  72.  
  73.    /* Get internet address of the host. We can do it either by calling
  74.       ngethostbyname, or by calling store_hostaddress, from
  75.       host.c. Storehostaddress is better since it caches calls to
  76.       gethostbyname. */
  77. #if 1
  78.    if (!store_hostaddress((unsigned char *)&sock_name.sin_addr, hostname))
  79.       return HOSTERR;
  80. #else /* never */
  81.    if (!(hptr = ngethostbyname(hostname)))
  82.       return HOSTERR;
  83.    /* Copy the address of the host to socket description. */
  84.    memcpy(&sock_name.sin_addr, hptr->h_addr, hptr->h_length);
  85. #endif
  86.    /* Set port and protocol */
  87.    sock_name.sin_family = AF_INET;
  88.    sock_name.sin_port = htons(port);
  89.    /* Make an internet socket, stream type. */
  90.    if ((*sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  91.       return CONSOCKERR;
  92.  
  93.    /* Connect the socket to the remote host. */
  94.    if (connect(*sock, (struct sockaddr *) &sock_name, sizeof (sock_name)))
  95.    {
  96.       if (errno == ECONNREFUSED)
  97.      return CONREFUSED;
  98.       else
  99.      return CONERROR;
  100.    }
  101. #ifdef DEBUG
  102.    if (opt.debug)
  103.       fprintf(opt.lfile, "Created fd %d.\n", *sock);
  104. #endif
  105.    return NOCONERROR;
  106. }
  107.  
  108. /* bindport does all the work necessary to bind a port, creating a
  109.    master socket msock. Use acceptport to call accept and receive the
  110.    actual socket. */
  111. uerr_t
  112. bindport(unsigned short *port)
  113. {
  114.    int optval = 1;
  115.  
  116.    msock = -1;
  117.    addr = (struct sockaddr *) & srv;
  118.    addrlen = sizeof(srv);
  119.    if ((msock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  120.       return CONSOCKERR;
  121.    if (setsockopt(msock, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)) < 0)
  122.       return CONSOCKERR;
  123.    srv.sin_family = AF_INET;
  124.    srv.sin_addr.s_addr = htonl(INADDR_ANY);
  125.    srv.sin_port = htons(*port);
  126.    if (bind(msock, addr, addrlen) < 0)
  127.    {
  128.       CLOSE(msock);
  129.       msock = -1;
  130.       return BINDERR;
  131.    }
  132. #ifdef DEBUG
  133.    if (opt.debug)
  134.       fprintf(opt.lfile, "Master socket fd %d bound.\n", msock);
  135. #endif
  136.    if (!*port)
  137.    {
  138.       if (getsockname(msock, addr, &addrlen) < 0)
  139.       {
  140.      CLOSE(msock);
  141.      msock = -1;
  142.      return CONPORTERR;
  143.       }
  144.       *port = ntohs(srv.sin_port);
  145.    }
  146.    if (listen(msock, 1) < 0)
  147.    {
  148.       CLOSE(msock);
  149.       msock = -1;
  150.       return LISTENERR;
  151.    }
  152.    return BINDOK;
  153. }
  154.  
  155. /* Acceptport uses msock and addrlen to call the accept system call
  156.    and return the data socket of the connection. It blocks the caller,
  157.    as per accept. */
  158. uerr_t
  159. acceptport(int *sock)
  160. {
  161. #ifdef HAVE_SELECT
  162.    if (select_fd(msock, opt.timeout) <= 0)
  163.       return ACCEPTERR;
  164. #endif
  165.    if ((*sock = accept(msock, addr, &addrlen)) < 0)
  166.       return ACCEPTERR;
  167. #ifdef DEBUG
  168.    if (opt.debug)
  169.       fprintf(opt.lfile, "Created socket fd %d.\n", *sock);
  170. #endif
  171.    return ACCEPTOK;
  172. }
  173.  
  174. /* Closes the sockets.  If sock is -1, close only msock (which is
  175.    private to connect.c.  */
  176. void
  177. closeport(int sock)
  178. {
  179.    /*shutdown(sock, 2);*/
  180.    if (sock != -1)
  181.       CLOSE(sock);
  182.    if (msock != -1)
  183.       CLOSE(msock);
  184.    msock = -1;
  185. }
  186.  
  187. /* Return the local IP address associated with the connection on fd.
  188.    It is returned in a static buffer. */
  189. unsigned char *
  190. conaddr(int fd)
  191. {
  192.    static unsigned char res[4];
  193.    struct sockaddr_in mysrv;
  194.    struct sockaddr *myaddr;
  195.    int len = sizeof(mysrv);
  196.  
  197.    myaddr = (struct sockaddr *)(&mysrv);
  198.    if (getsockname(fd, myaddr, &len) < 0)
  199.       return NULL;
  200.    memcpy(res, &mysrv.sin_addr, 4);
  201.    return res;
  202. }
  203.  
  204. #ifdef HAVE_SELECT
  205. /* select_fd - Waits for file descriptor fd to be readable, where
  206.    maxtime is the timeout in seconds. Returns 1 if fd is readable, 0
  207.    for timeout and -1 for error. */
  208. int
  209. select_fd(int fd, int maxtime)
  210. {
  211.    fd_set readfds, exceptfds;
  212.    struct timeval timeout;
  213.    int nfds;
  214.    
  215.    FD_ZERO(&readfds);
  216.    FD_SET(fd, &readfds);
  217.    FD_ZERO(&exceptfds);
  218.    FD_SET(fd, &exceptfds);
  219.    timeout.tv_sec = maxtime;
  220.    timeout.tv_usec = 0;
  221.    /* This is just a minor HPUX change to avoid warnings. */
  222. #ifndef __hpux
  223.    nfds = select(fd + 1, &readfds, NULL, &exceptfds, &timeout);
  224. #else  /* __hpux */
  225.    nfds = select(fd + 1, (int *)&readfds, NULL, (int *)&exceptfds, &timeout);
  226. #endif /* __hpux */
  227.    return nfds;
  228. }
  229. #endif /* HAVE_SELECT */
  230.  
  231. /* The same like read, but takes care of EINTR and uses select to
  232.    timeout the stale connections.  */
  233. int
  234. iread(int fd, char *buf, int len)
  235. {
  236.    int res;
  237.  
  238.    do
  239.    {
  240. #ifdef HAVE_SELECT
  241.       if (opt.timeout)
  242.       {
  243.      do
  244.      {
  245.         res = select_fd(fd, opt.timeout);
  246.      } while (res == -1 && errno == EINTR);
  247.      if (res <= 0)
  248.      {
  249.         /* Set errno to ETIMEDOUT on timeout. */
  250.         if (res == 0)
  251.            errno = ETIMEDOUT;
  252.         return -1;
  253.      }
  254.       }
  255. #endif
  256.       res = READ(fd, buf, len);
  257.    } while (res == -1 && errno == EINTR);
  258.    
  259.    return res;
  260. }
  261.  
  262. /* Similar to iread, but doesn't do select.  */
  263. int
  264. iwrite(int fd, char *buf, int len)
  265. {
  266.    int res;
  267.  
  268.    do
  269.    {
  270.       res = WRITE(fd, buf, len);
  271.    } while (res == -1 && errno == EINTR);
  272.    
  273.    return res;
  274. }
  275.